<?php

namespace Acme\FileManagerBundle\Controller;

use Acme\FileManagerBundle\Services\IFileManager;
use Acme\FileManagerBundle\Form\Type\FileType;
use Acme\FileManagerBundle\Form\Type\FileUploadType;
use Acme\FileManagerBundle\Entity\File;
use Acme\FileManagerBundle\Entity\Directory;
use Acme\FileManagerBundle\Services\PathBuilder;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Form\FormFactoryInterface;

class FileManagerController
{
    const TEMPLATE_FILE_UPLOAD = 'AcmeFileManagerBundle:FileManager:fileUpload.html.twig';
    const TEMPLATE_NEW_DIRECTORY = 'AcmeFileManagerBundle:FileManager:newDirectory.html.twig';
    const TEMPLATE_LIST_DIRECTORIES = 'AcmeFileManagerBundle:FileManager:listDirectory.html.twig';
    
    private $m_fileManager;
    private $m_templateEngine;
    private $m_formFactory;
    
    public function __construct(IFileManager $fileManager, EngineInterface $templateEngine, FormFactoryInterface $formFactory, \AppKernel $kernel)
    {
        $this->m_fileManager = $fileManager;
        $this->m_templateEngine = $templateEngine;
        $this->m_formFactory = $formFactory;
        
        $rootDirectory = $kernel->getRootDir() . '/files';
        $this->m_fileManager->setRootDirectory($rootDirectory);
    }
    
    public function listDirectoryAction($path, Request $request)
    {
        $pathBuilder = new PathBuilder($path);
        $files = $this->m_fileManager->listDirectory($pathBuilder->getPath());
        
        // Для защиты от CSRF
        $CSRFToken = md5(uniqid(rand(), true));
        $request->getSession()->setFlash('csrf_protection', $CSRFToken);
        
        return $this->m_templateEngine->renderResponse(self::TEMPLATE_LIST_DIRECTORIES, array(
            'path' => $pathBuilder,
            'files' => $files,
            'CSRFToken' => \urlencode($CSRFToken)
        ));
    }
    
    public function downloadFileAction($path)
    {
        $file = $this->m_fileManager->readFile($path);
        
        $response = new Response($file->getContent(), 200);
        
        // application/octet-stream вместо getMimeType
        $response->headers->set('Content-Type', 'application/octet-stream');
        $response->headers->set('Content-Desposition', sprintf('attachment;filename="%s";', $file->getName()));
        $response->headers->set('Content-Length', $file->getSize());
        $response->headers->set('Content-Transfer-Encoding', 'binary');
        
        $response->sendHeaders();
        
        return $response;
    }
    
    public function createDirectoryAction($path, Request $request)
    {
        $pathBuilder = new PathBuilder(ltrim($path, '/'));
        
        $directory = new Directory;
        $directory->setRelativePath($pathBuilder->getPath());
        
        $form = $this->m_formFactory->create(new FileType, $directory);
        
        if ($request->getMethod() == 'POST')
        {
            $form->bindRequest($request);
            
            if ($form->isValid())
            {
                $this->m_fileManager->createDirectory($directory);
                
                return new RedirectResponse("/{$directory->getRelativePath()}");
            }
        }
        
        return $this->m_templateEngine->renderResponse(self::TEMPLATE_NEW_DIRECTORY, array(
            'path' => $pathBuilder,
            'form' => $form->createView()
        ));
    }
    
    public function uploadFileAction($path, Request $request)
    {
        $pathBuilder = new PathBuilder(ltrim($path, '/'));
        
        $form = $this->m_formFactory->create(new FileUploadType, new File);
        
        if ($request->getMethod() == 'POST')
        {
            $form->bindRequest($request);
            
            if ($form->isValid())
            {
                $uploadedFile = $form['content']->getData();
                
                $realPath = $this->m_fileManager->getRealPath($pathBuilder->getPath());
                $originalName = $uploadedFile->getClientOriginalName();
                $fileName = $realPath . $originalName;
                
                $uploadedFile->move($realPath, $originalName);
                
                \chmod($fileName, 0644);
                
                return new RedirectResponse($path);
            }
        }
        
        return $this->m_templateEngine->renderResponse(self::TEMPLATE_FILE_UPLOAD, array(
            'path' => $pathBuilder,
            'form' => $form->createView()
        ));
    }
    
    public function deleteFileAction($path, Request $request)
    {
        // Удаляем лишний slash, который может быть в случае, если удаляемый файл - папка
        $path = rtrim($path, '/');
        
        $CSRFToken = $request->getSession()->getFlash('csrf_protection');
        $token = \urldecode($request->get('token'));
        
        if ($CSRFToken !== $token || $token === null) {
            throw new \Exception('CSRF Detected');
        }
        
        $this->m_fileManager->deleteFile($path);
        
        $referer = $request->headers->get('referer');
        
        return new RedirectResponse($referer);
    }
}